﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Runtime;
using System.Runtime.Serialization;
using System.Globalization;

namespace ImPM.Application
{
    [Serializable]
    public class ImPMException : Exception
    {
        // Methods
        public ImPMException()
            : this(null, null, -2147220970, false)
        {
        }

        public ImPMException(string message)
            : this(message, null, -2147220970, false)
        {
        }

        public ImPMException(int errorCode, params object[] arguments)
            : this(FormatMessage(errorCode, arguments), null, errorCode, false)
        {
        }

        protected ImPMException(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        public ImPMException(string message, Exception innerException)
            : this(message, innerException, -2147220970, false)
        {
        }

        public ImPMException(string message, int errorCode)
            : this(message, null, errorCode, false)
        {
        }

        public ImPMException(Exception innerException, int errorCode, params object[] arguments)
            : this(FormatMessage(errorCode, arguments), innerException, errorCode, false)
        {
        }

        public ImPMException(string message, Exception innerException, int errorCode)
            : this(message, innerException, errorCode, false)
        {
        }

        public ImPMException(string message, int errorCode, bool enableTrace)
            : this(message, null, errorCode, false, enableTrace)
        {
        }

        protected ImPMException(string message, Exception innerException, int errorCode, bool isFlowControlException)
            : this(message, innerException, errorCode, isFlowControlException, true)
        {
        }

        protected ImPMException(string message, Exception innerException, int errorCode, bool isFlowControlException, bool enableTrace)
            : base(message, innerException)
        {
            base.HResult = errorCode;
            if (innerException == null)
            {
                if (enableTrace)
                {
                    ImPMTrace.TraceFormat(ImPMTrace.DefaultTraceSetting, TraceCategory.Exception, TraceLevel.Error, "Crm Exception: Message: {0}, ErrorCode: {1}", new object[] { message, base.HResult });
                }
            }
            else if (enableTrace)
            {
                ImPMTrace.TraceFormat(ImPMTrace.DefaultTraceSetting, TraceCategory.Exception, TraceLevel.Error, "Crm Exception: Message: {0}, ErrorCode: {1}, InnerException: {2}", new object[] { message, base.HResult, innerException });
            }
            if (!isFlowControlException)
            {
                //MiniDump.CreateDump(MiniDumpReasons.CrmExceptionConstruction, this);
            }
        }

        public static void Assert(bool condition, string message)
        {
            ImPMException exception = null;
            if (!condition)
            {
                exception = new ImPMException(message, -2147220970);
            }
            if (exception != null)
            {
                throw exception;
            }
        }

        public static void Assert(bool condition, string message, params object[] args)
        {
            Assert(condition, string.Format(CultureInfo.InvariantCulture, message, args));
        }

        public static string ExceptionToString(Exception ex)
        {
            StringBuilder builder = new StringBuilder(0x400);
            string str = "Unhandled ";
            for (Exception exception = ex; exception != null; exception = exception.InnerException)
            {
                builder.AppendFormat(CultureInfo.InvariantCulture, "{0}Exception: {1}", new object[] { str, exception.GetType().FullName });
                if (exception.Message.Length > 0)
                {
                    builder.AppendFormat(CultureInfo.InvariantCulture, ": {0}", new object[] { exception.Message });
                }
                builder.Append(Environment.NewLine);
                builder.Append(exception.StackTrace);
                builder.Append(Environment.NewLine);
                str = "Inner ";
            }
            return builder.ToString();
        }

        public static string FormatMessage(int errorCode, params object[] arguments)
        {
            string errorMessage = (errorCode).ToString();
            try
            {
                return string.Format(CultureInfo.InvariantCulture, errorMessage, arguments);
            }
            catch (FormatException)
            {
                StringBuilder builder = new StringBuilder(errorMessage);
                for (int i = 0; i < arguments.Length; i++)
                {
                    builder.Append(string.Format(CultureInfo.InvariantCulture, "\nData[{0}] = \"{1}\"", new object[] { i, arguments[i] }));
                }
                return builder.ToString();
            }
        }

        // Properties
        public int ErrorCode
        {
            get
            {
                return base.HResult;
            }
        }
    }


}
